package org.ruoyi.common.dhuman.backup;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

/**
 * 高质量绿幕视频处理类
 * 使用FFmpeg处理含绿幕的视频(result.mp4)和蒙版视频(mask.mp4)
 * 生成高质量输出视频
 */
public class HighQualityGreenScreenProcessor {

	private String ffmpegPath;

	/**
	 * 构造函数
	 *
	 * @param ffmpegPath FFmpeg可执行文件路径，如果为null则使用系统PATH中的ffmpeg
	 */
	public HighQualityGreenScreenProcessor(String ffmpegPath) {
		this.ffmpegPath = ffmpegPath != null ? ffmpegPath : "ffmpeg";
	}

	/**
	 * 高质量处理绿幕视频
	 * 去除绿幕背景并结合蒙版视频输出高质量结果
	 *
	 * @param videoPath  绿幕视频路径 (result.mp4)
	 * @param maskPath   蒙版视频路径 (mask.mp4)
	 * @param outputPath 输出视频路径
	 * @throws IOException          IO异常
	 * @throws InterruptedException 中断异常
	 */
	public void processHighQualityVideo(String videoPath, String maskPath, String outputPath)
		throws IOException, InterruptedException {

		// 构建高质量FFmpeg命令
		List<String> command = new ArrayList<>();
		command.add(ffmpegPath);

		// 输入文件
		command.add("-i");
		// 绿幕视频
		command.add(videoPath);
		command.add("-i");
		// 蒙版视频
		command.add(maskPath);

		// 高质量编码参数
		command.add("-c:v");
		// 使用H.264编码器
		command.add("libx264");

		// 高质量预设和CRF值
		command.add("-preset");
		// 编码速度与压缩率的平衡
		command.add("slow");
		command.add("-crf");
		// 恒定速率因子，值越小质量越高(18为视觉无损)
		command.add("18");

		// 高级视频参数
		command.add("-profile:v");
		// H.264 high profile
		command.add("high");
		command.add("-level");
		// 编码级别
		command.add("4.2");
		command.add("-pix_fmt");
		// 像素格式兼容性
		command.add("yuv420p");

		// 音频参数
		command.add("-c:a");
		// AAC音频编码
		command.add("aac");
		command.add("-b:a");
		// 音频比特率
		command.add("192k");
		command.add("-ar");
		// 音频采样率
		command.add("48000");

		// 滤镜处理
		command.add("-filter_complex");
		// 使用chromakey进行高质量绿幕抠图，然后叠加蒙版
		// 参数说明: color=0x00ff00(绿色), similarity=0.1(低相似度提高精度), blend=0.1(柔和边缘)
		command.add("[0:v]chromakey=0x00ff00:0.1:0.1[fg];[fg][1:v]overlay=0:0[outv]");
		command.add("-map");
		// 映射处理后的视频
		command.add("[outv]");
		command.add("-map");
		// 映射原始音频(如果存在)
		command.add("0:a?");

		// 输出文件
		command.add(outputPath);

		System.out.println("执行命令: " + String.join(" ", command));

		// 执行命令
		ProcessBuilder processBuilder = new ProcessBuilder(command);
		processBuilder.redirectErrorStream(true);
		Process process = processBuilder.start();

		// 实时输出处理日志
		BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
		String line;
		while ((line = reader.readLine()) != null) {
			System.out.println(line);
		}

		int exitCode = process.waitFor();
		if (exitCode != 0) {
			throw new RuntimeException("FFmpeg处理失败，退出码: " + exitCode);
		}
	}

	/**
	 * 超高质量处理（适用于专业用途）
	 *
	 * @param videoPath  绿幕视频路径
	 * @param maskPath   蒙版视频路径
	 * @param outputPath 输出视频路径
	 * @throws IOException          IO异常
	 * @throws InterruptedException 中断异常
	 */
	public void processUltraHighQualityVideo(String videoPath, String maskPath, String outputPath)
		throws IOException, InterruptedException {

		List<String> command = new ArrayList<>();
		command.add(ffmpegPath);
		command.add("-i");
		command.add(videoPath);
		command.add("-i");
		command.add(maskPath);

		// 超高质量编码参数
		command.add("-c:v");
		command.add("libx264");
		command.add("-preset");
		// 最慢但最高压缩率
		command.add("veryslow");
		command.add("-crf");
		// 更高的质量
		command.add("15");
		command.add("-profile:v");
		// 更高质量的profile
		command.add("high444");
		command.add("-level");
		command.add("5.1");
		command.add("-pix_fmt");
		// 4:4:4采样更高质量
		command.add("yuv444p");

		// 高质量音频
		command.add("-c:a");
		// 无损音频编码
		command.add("flac");
		command.add("-ar");
		command.add("48000");

		// 高级滤镜处理
		command.add("-filter_complex");
		// 使用更精确的色度键控和边缘处理
		command.add("[0:v]chromakey=0x00ff00:0.08:0.05[fg];" +
			"[fg]smartblur=lr=1:ls=-1:lt=-1[fg_blur];" +
			"[fg_blur][1:v]overlay=0:0:format=rgb[outv]");
		command.add("-map");
		command.add("[outv]");
		command.add("-map");
		command.add("0:a?");

		command.add(outputPath);

		System.out.println("执行超高质量命令: " + String.join(" ", command));

		ProcessBuilder processBuilder = new ProcessBuilder(command);
		processBuilder.redirectErrorStream(true);
		Process process = processBuilder.start();

		BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
		String line;
		while ((line = reader.readLine()) != null) {
			System.out.println(line);
		}

		int exitCode = process.waitFor();
		if (exitCode != 0) {
			throw new RuntimeException("FFmpeg处理失败，退出码: " + exitCode);
		}
	}

	/**
	 * 使用双重键控提高精度
	 *
	 * @param videoPath  绿幕视频路径
	 * @param maskPath   蒙版视频路径
	 * @param outputPath 输出视频路径
	 * @throws IOException          IO异常
	 * @throws InterruptedException 中断异常
	 */
	public void processWithDualKeying(String videoPath, String maskPath, String outputPath)
		throws IOException, InterruptedException {

		List<String> command = new ArrayList<>();
		command.add(ffmpegPath);
		command.add("-i");
		command.add(videoPath);
		command.add("-i");
		command.add(maskPath);

		// 高质量参数
		command.add("-c:v");
		command.add("libx264");
		command.add("-preset");
		command.add("medium");
		command.add("-crf");
		command.add("18");
		command.add("-pix_fmt");
		command.add("yuv420p");

		command.add("-c:a");
		command.add("aac");
		command.add("-b:a");
		command.add("192k");

		// 双重键控滤镜
		command.add("-filter_complex");
		// 先使用colorkey，再使用alphaextract提取alpha通道，最后与蒙版叠加
		command.add("[0:v]colorkey=0x00ff00:0.1:0.1[ckout];" +
			"[ckout]alphaextract[alpha];" +
			"[ckout][alpha]alphamerge[fg];" +
			"[fg][1:v]overlay=0:0[outv]");
		command.add("-map");
		command.add("[outv]");
		command.add("-map");
		command.add("0:a?");

		command.add(outputPath);

		ProcessBuilder processBuilder = new ProcessBuilder(command);
		processBuilder.redirectErrorStream(true);
		Process process = processBuilder.start();

		BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
		String line;
		while ((line = reader.readLine()) != null) {
			System.out.println(line);
		}

		int exitCode = process.waitFor();
		if (exitCode != 0) {
			throw new RuntimeException("FFmpeg处理失败，退出码: " + exitCode);
		}
	}

	/**
	 * 主方法 - 执行高质量视频处理
	 */
	public static void main(String[] args) {
		// 指定视频文件路径
		String videoPath = "C:\\Users\\Admin\\Videos\\result.mp4";
		String maskPath = "C:\\Users\\Admin\\Videos\\mask.mp4";
		String outputPath = "C:\\Users\\Admin\\Videos\\output_high_quality_.mp4";

		// 创建处理器实例
		HighQualityGreenScreenProcessor processor = new HighQualityGreenScreenProcessor(null);

		File videoFile = new File(videoPath);
		File maskFile = new File(maskPath);

		// 检查输入文件是否存在
		if (!videoFile.exists()) {
			System.err.println("错误: 绿幕视频文件不存在 - " + videoPath);
			return;
		}

		if (!maskFile.exists()) {
			System.err.println("错误: 蒙版文件不存在 - " + maskPath);
			return;
		}

		try {
			System.out.println("开始高质量处理绿幕视频...");
			System.out.println("绿幕视频: " + videoPath);
			System.out.println("蒙版视频: " + maskPath);
			System.out.println("输出文件: " + outputPath);

			// 选择处理方法
			// 1. 标准高质量处理
			processor.processHighQualityVideo(videoPath, maskPath, outputPath);

			// 2. 如需超高质量，可使用以下方法（处理时间较长）
			// processor.processUltraHighQualityVideo(videoPath, maskPath, outputPath);

			// 3. 如需更高精度，可使用双重键控
			// processor.processWithDualKeying(videoPath, maskPath, "C:\\Users\\Admin\\Videos\\output_dual_key.mp4");

			System.out.println("高质量视频处理完成!");
			System.out.println("输出文件位置: " + outputPath);

		} catch (Exception e) {
			System.err.println("视频处理失败: " + e.getMessage());
			e.printStackTrace();
		}
	}
}
